using System;
using System.Collections.Generic;
using System.Threading;

namespace Client
{
    public class Task
    {
        private Int32 m_ms;  // Milliseconds;

        public Task(Int32 seconds)
        {
            m_ms = seconds * 1000;
        }

        public Int32 DuracaoTask
        {
            get { return m_ms; }
            set { m_ms = value * 1000; }
        }

        // Synchronous version of time-consuming method
        public DateTime DoTask()
        {
            Thread.Sleep(m_ms);  // Simulate time-consuming task
            return DateTime.Now; // Return value indicates when task completed
        }

        // Asynchronous version of time-consuming method (Begin part)
        public IAsyncResult BeginDoTask(AsyncCallback callback, Object state)
        {
            // Create IAsyncResult object identifying the asynchronous operation
            AsyncResult<DateTime> ar = new AsyncResult<DateTime>(callback, state);

            // Use a thread pool thread to perform the operation
            ThreadPool.QueueUserWorkItem(DoTaskHelper, ar);
            return ar;  // Return the IAsyncResult to the caller
        }

        // Asynchronous version of time-consuming method (End part)
        public DateTime EndDoTask(IAsyncResult asyncResult)
        {
            // We know that the IAsyncResult is really an AsyncResult<DateTime> object
            AsyncResult<DateTime> ar = (AsyncResult<DateTime>)asyncResult;

            // Wait for operation to complete, then return result or throw exception
            return ar.Result; // .EndInvoke();
        }

           // Asynchronous version of time-consuming method (private part to set completion result/exception)
        private void DoTaskHelper(Object asyncResult)
        {
            // We know that the IAsyncResult is really an AsyncResult<DateTime> object
            AsyncResult<DateTime> ar = (AsyncResult<DateTime>)asyncResult;
            try
            {
                // Perform the operation; if sucessful set the result
                ar.Complete(DoTask(), false);
            }
            catch (Exception e)
            {
                // If operation fails, set the exception
                ar.HandleException(e, false);
            }
        }
    }
}
